#include <iostream>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <thread>
#include <boost/container/static_vector.hpp>
#include "lock_free_ring.h"

template <class T>
T *CreateProdSharMemory(int nKey, int &shmID)

{
    // 创建共享内存
    shmID = shmget(nKey, sizeof(T), 0666 | IPC_CREAT);
    if (shmID < 0)
    {
        // todo 输出log 共享内存创建失败
        std::cerr << "shmget fail, " << errno << std::endl;
        return nullptr;
    }

    // 映射共享内存到进程地址空间
    T *pDataField = (T *)shmat(shmID, 0, 0);
    if (((void *)(-1)) == (void *)pDataField)
    {
        // 映射失败
        std::cerr << "shmat failed: " << errno << std::endl;
        perror("shmat ");
        return nullptr;
    }

    // 映射成功
    return pDataField;
}

void push_thread(lock_free_ring<size_t, QUEUE_SIZE> &lrq, size_t id)
{
    size_t i = id * (TOTAL_COUNT / push_thread_cnt);
    size_t target_cnt = i + (TOTAL_COUNT / push_thread_cnt);
    for (; i < target_cnt; ++i)
    {
        while (!lrq.push(i))
        {
            __builtin_ia32_pause();
        }
    }
}

int main()
{
    lock_free_ring_test *pDataField = nullptr;
    int shmID = 0;
    pDataField = CreateProdSharMemory<lock_free_ring_test>(333, shmID);
    pDataField->ring.init();

    while (true)
    {
        pDataField->stop = false;
        pDataField->finish = false;
        boost::container::static_vector<std::thread, push_thread_cnt>
            push_threads;
        for (size_t i = 0; i < push_thread_cnt; ++i)
            push_threads.push_back(std::thread(push_thread, std::ref(pDataField->ring), i));

        for (size_t i = 0; i < push_thread_cnt; ++i)
            push_threads[i].join();

        pDataField->stop = true;

        while (!pDataField->finish)
        {
            __builtin_ia32_pause();
        }
    }

    return 0;
}